#include "inibase.h"
#include <QTextCodec>
#include <QDebug>

iniBase::iniBase(QObject *parent)
    : QObject{parent}
{

}

QStringList ini第一行列表;
QStringList ini第二行列表;

///读配置文件,   ini文件地址，节名，键名
///无法读出"\"号
QStringList Read_CONFIG_INI(QString iniFile, QString section, QString key)
{
    //分配打开Config.ini文件的内存
    QSettings Config_ini_Read(iniFile , QSettings::IniFormat);
    Config_ini_Read.setIniCodec("UTF-8"); // 让 ini 支持中文

    QStringList value;
    QString 具体的键名 = "/" + section + "/" + key ;

    QVariant 确定有值=Config_ini_Read.value(具体的键名);
//    qDebug()<<"字符"<<确定有值;
//    qDebug()<<"字符"<<!确定有值.isNull();
//    qDebug()<<"字符"<<!确定有值.isValid();
    if(!确定有值.isNull()){value = 确定有值.toStringList();}
    else{value.append("NULL");}
    //qDebug()<<"字符"<<value;
    return value;
}

QStringList ini读尖括号格式(QString ini文件, QString 键名)
{
    QStringList 键值列表;
    QString 返回文本;
    QString 临时文本;
    QFile file(ini文件);
    if (file.open (QIODevice::ReadOnly))
    {
        QTextStream in(&file);
        in.seek(0); // 将文件指针移动到文件开头,计数是以字符计数，不是行数。
        int index=0;

        while(!in.atEnd()) {//读取全文,看键值是有相同的.
            返回文本 = in.readLine(); // 读取一行文本
            index = 返回文本.indexOf("=");
            if(index-1>=0)//数组索引必须>=0
                临时文本=返回文本.mid(0,index);//取出键名
            if(临时文本==键名)
            {
                临时文本=返回文本.mid(index+1,返回文本.length()-index);//取出键值
                if(临时文本.length() == 0)
                {
                    return 键值列表;//返回一个空的字符列表.
                }
                键值列表=临时文本.split(QChar(','));
            }
            //找不到不用处理, 反正后面会返回一个空的字符列表.
        }
    }

    return 键值列表;
}
///读的使用方式：
//#include "./code/inibase.h"
//#define 词典html格式 "词典/新华大字典.ini"
//QStringList 查表=Read_CONFIG_INI(词典html格式,"","<~~>");//不需要节名
//qDebug() << "具体的键名"<<查表[0] ;

//写配置文件
int Write_CONFIG_INI(QString iniFile, QString section, QString key, QStringList value)
{
    //分配打开Config.ini文件的内存
    QSettings  Config_ini_Write(iniFile, QSettings::IniFormat); ;
    Config_ini_Write.setIniCodec("UTF-8"); // 可以 ini 支持中文，但是无法支持中文节名和键名

    QString 具体的键名 = "/" + section + "/" + key ;
   // qDebug() << "具体的键名"<<具体的键名 ;
    Config_ini_Write.setValue(具体的键名,value);

    return 0;
}



QString 生成新键名(QString iniFile)
{
    QString 返回文本="初始量";
    QFile file(iniFile);
#pragma region {///读出文件中最后一行。
   if (file.open (QIODevice::ReadOnly))
   {
        QTextStream in(&file);
        in.seek(0); // 将文件指针移动到文件开头,计数是以字符计数，不是行数。
        int i=0;
        while(!in.atEnd()) {//主要用来获取文本行数。
            i++;
            返回文本 = in.readLine(); // 读取一行文本
            }
        if(返回文本=="")//是"",不是 \r\n; 要求最后一行是空的才进来处理。
        {
           int j=i;

           do{
                --j;
                in.seek(0);
                while(--i){
                    返回文本 = in.readLine(); // 读取一行文本
                }
                i=j;
               //qDebug()<<"循环"<<返回文本;
                //qDebug()<<"j"<<j;
                if(!j) break;//j为0时退出循环,防止文本中是多个空行从而造成死循环.

            }while(!返回文本.length());//得到的长度不为0就退出循环。
        }
    }
    file.close();


#pragma endregion }///读出文件中最后一行


    if(返回文本=="初始量") {    return 返回文本="<~~>";}

    int 左尖 = 返回文本.indexOf('<');//找出<>号的位置, 抽取<>中的内容.
    int 右尖 = 返回文本.indexOf('>');
    QString midStr = 返回文本.mid(左尖+1, 右尖-1);
    //qDebug()<<"midStr"<<midStr;
    if(midStr.length()<1 || midStr.length()>5 || 返回文本.length()<3){    return 返回文本="<~~>";}

    //支持5位数就可以.
    int 剩余长度=midStr.length();

//    QString 临时 = midStr.mid(--剩余长度, 1);
//    QByteArray ba = 临时.toLatin1();
//    char 个 = ba[0];//QString转QByteArray再转char.

    QString 个 = midStr.mid(--剩余长度, 1);//分离出个十百千万位.
    QString 十 = midStr.mid(--剩余长度, 1);
    QString 百 = midStr.mid(--剩余长度, 1);
    QString 千 = midStr.mid(--剩余长度, 1);
    QString 万 = midStr.mid(--剩余长度, 1);

   // qDebug()<<"剩余长度"<<剩余长度;
   // qDebug()<<"右边字符"<<万<<千<<百<<十<<个;

#pragma region {///号码递增和进位,只支持5位及以内.10万个标签已经很多了.
        if(个=="")   { 个="~"; goto 不进位;}//null
        if(个=="~")  { 个="`"; goto 不进位;}//0
        if(个=="`")  { 个="^"; goto 不进位;}//1
        if(个=="^")  { 个="-"; goto 不进位;}//2
        if(个=="-")  { 个="+"; goto 不进位;}//3
        if(个=="+")  { 个="*"; goto 不进位;}//4
        if(个=="*")  { 个="&"; goto 不进位;}//5
        if(个=="&")  { 个="%"; goto 不进位;}//6
        if(个=="%")  { 个="$"; goto 不进位;}//7
        if(个=="$")  { 个="#"; goto 不进位;}//8
        if(个=="#")  { 个="~";   }//9

        if(十=="")   { 十="~"; goto 不进位;}//null
        if(十=="~")  { 十="`"; goto 不进位;}//0
        if(十=="`")  { 十="^"; goto 不进位;}//1
        if(十=="^")  { 十="-"; goto 不进位;}//2
        if(十=="-")  { 十="+"; goto 不进位;}//3
        if(十=="+")  { 十="*"; goto 不进位;}//4
        if(十=="*")  { 十="&"; goto 不进位;}//5
        if(十=="&")  { 十="%"; goto 不进位;}//6
        if(十=="%")  { 十="$"; goto 不进位;}//7
        if(十=="$")  { 十="#"; goto 不进位;}//8
        if(十=="#")  { 十="~";   }//9

        if(百=="")   { 百="~"; goto 不进位;}//null
        if(百=="~")  { 百="`"; goto 不进位;}//0
        if(百=="`")  { 百="^"; goto 不进位;}//1
        if(百=="^")  { 百="-"; goto 不进位;}//2
        if(百=="-")  { 百="+"; goto 不进位;}//3
        if(百=="+")  { 百="*"; goto 不进位;}//4
        if(百=="*")  { 百="&"; goto 不进位;}//5
        if(百=="&")  { 百="%"; goto 不进位;}//6
        if(百=="%")  { 百="$"; goto 不进位;}//7
        if(百=="$")  { 百="#"; goto 不进位;}//8
        if(百=="#")  { 百="~";  }//9

        if(千=="")   { 千="~"; goto 不进位;}//null
        if(千=="~")  { 千="`"; goto 不进位;}//0
        if(千=="`")  { 千="^"; goto 不进位;}//1
        if(千=="^")  { 千="-"; goto 不进位;}//2
        if(千=="-")  { 千="+"; goto 不进位;}//3
        if(千=="+")  { 千="*"; goto 不进位;}//4
        if(千=="*")  { 千="&"; goto 不进位;}//5
        if(千=="&")  { 千="%"; goto 不进位;}//6
        if(千=="%")  { 千="$"; goto 不进位;}//7
        if(千=="$")  { 千="#"; goto 不进位;}//8
        if(千=="#")  { 千="~";  }//9

        if(万=="")   { 万="~"; goto 不进位;}//null
        if(万=="~")  { 万="`"; goto 不进位;}//0
        if(万=="`")  { 万="^"; goto 不进位;}//1
        if(万=="^")  { 万="-"; goto 不进位;}//2
        if(万=="-")  { 万="+"; goto 不进位;}//3
        if(万=="+")  { 万="*"; goto 不进位;}//4
        if(万=="*")  { 万="&"; goto 不进位;}//5
        if(万=="&")  { 万="%"; goto 不进位;}//6
        if(万=="%")  { 万="$"; goto 不进位;}//7
        if(万=="$")  { 万="#"; goto 不进位;}//8
        if(万=="#")  { return 返回文本="<~~~~~~>";}//超过5位后我也不知道如何处理
不进位:
    返回文本="<"+万+千+百+十+个+">";
#pragma endregion }///号码递增和进位,只支持5位及以内.
  //  qDebug()<<"右边字符"<<万<<千<<百<<十<<个;
  //  qDebug()<<"返回文本"<<返回文本;
    return 返回文本;

}


QString 规整化词典模板(QString 原始html, QString INI文件)
{
    QString 单行文本;

    QStringList ini写入;//这是个共用的变量.
    ini写入.append("词典");//表的类型是笔记
    ini写入指定键值(INI文件,"<^>",ini写入);

    QStringList html多行 = 原始html.split("\n");// 按行分割文本
    QStringList html元素;
    int 第几行html=0;
    int index=-1;

    QStringList 表列名;
    QStringList 表列设置;
    表列设置.append("");//先加入空的, 为了能用[0]
    ///先找到ID
    for(int i=0;第几行html < html多行.length();第几行html++)//遍历整个html文件
    {
        html元素=单行html元素拆分(html多行[i]);
        i++;
        bool 未找到ID=true;
        for(int j=0;j<html元素.length(); j++)//先找到ID
        {
            index=html元素[j].indexOf("---ID");
            if(index>=0 && index<2)//防止-号前有空格,也防止这行不是ID, 所以要加个小于2
            {
                未找到ID=false;
                表列名.append("ID");
                QStringList ID前标签;
                ID前标签.append("");
                bool 未找到递增=true;
                bool 未找到不显示=true;
                for(int k=0;k<html元素.length(); k++)//写入ID前的html标签,  写入ID递增方式和是否显示
                {
                    if(k<j)
                    {   ID前标签[0]+=html元素[k];   }
                    if(k==j)
                    {   ini写入指定键值(INI文件,"<~~>",ID前标签);}//写入ID前的html标签
                    if(k>=j)
                    {
                        index=html元素[k].indexOf("自动递增");
                        int index1=html元素[k].indexOf("用户指定");
                        int index2=html元素[k].indexOf("不显示");
                        if(index != -1)
                        {  表列设置[0]+="自动递增|"; 未找到递增=false;}
                        if(index1 != -1)
                        {  表列设置[0]+="用户指定|";  未找到递增=false;}
                        if(index2 != -1)
                        {  表列设置[0]+="不显示"; 未找到不显示=false;}

                        if(html元素.length()== k+1)//到了最后一行
                        {
                            if(未找到递增)
                            {  表列设置[0]+="自动递增|"; }
                            if(未找到不显示)
                            {  表列设置[0]+="显示"; }
 qDebug()<<"能到这里吗"<<k<<i<<第几行html;
                            第几行html++;
                            goto 找到ID了;
                        }
                    }
                }
            }
        }
        if( html多行.length()==第几行html+1)//如果找到最后一行
        {
            if(未找到ID)  return 单行文本="错误, 未找到ID";
            else         return 单行文本="错误, 只找到ID";
        }
    }

找到ID了:
//    qDebug()<<"表列名rr"<<表列名;
//    qDebug()<<"表列设置ee"<<表列设置;

    ///保存ID的显示格式到 <~`>
    html元素=单行html元素拆分(html多行[第几行html]);
    第几行html++;
    ini写入[0]="";
    for(int i=0;i<html元素.length(); i++)//将ID数字前的html标签, 写入到<~`>
    {
        index=html元素[i].indexOf("<");
        if(index == 0)
        {
            ini写入[0]+=html元素[i];
        }
        else
        {
            ini写入指定键值(INI文件,"<~`>",ini写入);
            break;
        }
    }


     ///只找其它列名, 和列是否不换行\的格式, 写入到ini中.
     /// 后面添加词条时, 根据格式再减去<p></p>标签
    for(;第几行html < html多行.length();第几行html++)//遍历整个html文件
    {
        html元素=单行html元素拆分(html多行[第几行html]);
        for(int j=0;j<html元素.length(); j++)//先找到ID
        {
            index=-1;
            index=html元素[j].indexOf("---\\\\");//  符号---\\是结束符
            if(index != -1) {goto 全部找完了; qDebug()<<"全部找到了规整化词典模板";}

            index=html元素[j].indexOf("---");//先找到连续的三个-号
            if(index>=0 && index<2)//防止-号前有空格,也防止这行不是ID, 所以要加个小于2
            {

                单行文本=html元素[j].replace('-', ' ');  // - 号替换为空格
                单行文本=单行文本.remove(QRegExp("\\s+"));  //去除所有空格
                index=-1;
                index=单行文本.indexOf("\\");//反斜杠 \ 表示此列跟其下一列在显示在文本框中时是同一行.

                if(单行文本.length()>0)
                {
                    if(index>0)// 反斜杠 \ 必须要在文字之后
                    {
                        单行文本=单行文本.mid(0,index);
                        表列名.append(单行文本);
                        表列设置.append("\\");
                    }
                    else
                    {
                        表列名.append(单行文本);
                        表列设置.append("");
                    }

                }
                else continue;//空无一物, 说明没有列名
            }
        }

    }
全部找完了:

    qDebug()<<"表列名rr"<<表列名;
    qDebug()<<"表列设置ee"<<表列设置;
    ini写入指定键值(INI文件,"<~>",表列名);
    ini写入指定键值(INI文件,"<`>",表列设置);

    if(表列名.length()>1)//默认在索引框中显示ID后的那个列名
    {
        ini写入.clear();
        ini写入.append(表列名[1]);
        ini写入指定键值(INI文件,"<->",ini写入);
    }

    return 单行文本;

}

///使用时直接输入内容,查询是否有重复,决定是否写入内容,返回新键名或已存在的键名.
///输入的 键值 内容与已有的键值相同,则返回已有的键名.
///若没有相同的, 则新增加键名并写入新键值, 返回新键名.
QString ini写入html标签(QString ini文件,QString 键值)
{
    if(键值.length()<10)//长度大于10才缩键名
    {
        return 键值;
    }
    QString 返回文本;
    QString 临时文本;
    QFile file(ini文件);
    bool 相同内容=false;
    if (file.open (QIODevice::ReadWrite))
    {
        QTextStream in(&file);
        in.seek(0); // 将文件指针移动到文件开头,计数是以字符计数，不是行数。
        int index=0;

        while(!in.atEnd()) //读取全文,看键值是否有相同的.
        {
            返回文本 = in.readLine(); // 读取一行文本
            index = 返回文本.indexOf("=");
            if(index-1>=0)//数组索引必须>=0
                临时文本=返回文本.mid(index+1,返回文本.length()-index);//取出键值,即html格式.
            if(临时文本==键值)
            {
                相同内容=true;
                break;
            }
        }
        if(相同内容)
        {
            返回文本=返回文本.mid(0,index);//将相同内容行的键名取出,再退出该函数.
            return 返回文本;
        }
        else
        {
                QString 键名=生成新键名(ini文件);//生成最新的键名
                in.seek(file.size());
                in<<键名<<"="<<键值<<"\r\n";
                return 键名;
        }
    }


    //下面是内容没有相同时的处理.//因为会把键名变成%数字表示,不用它.
//    QString 键名=生成新键名(ini文件);//生成最新的键名
//    Write_CONFIG_INI(ini文件,"", 键名, 键值);//新的html格式写到ini中.
    return 返回文本="NULL";
}

///对已知键名的内容写入到ini文件.
///键名可以是已有或还没有的.
QString ini写入指定键值(QString ini文件,QString 键名,QStringList 键值)
{
    QStringList 新ini文件内容;
    QString 返回文本;
    bool 已找到=false;
    QFile file(ini文件);
    if (file.open (QIODevice::ReadWrite))
    {
        QTextStream in(&file);
        in.seek(0); // 将文件指针移动到文件开头,计数是以字符计数，不是行数。
        int index=-3;//做个特殊的值,防止一开始就条件成立.  -2已找到并更新, -1没找到,  0是找没未更新

        while(!in.atEnd()) {//读取全文,看键值是有相同的.
            返回文本 = in.readLine(); // 读取一行文本

            index = 返回文本.indexOf(键名);
            if(index==0)//如果有重复的键名,也会被替换.  //内容相同,不被替代的功能也没做.
            {

                已找到=true;
                返回文本=键名+"=";

                for(int i=0;i<键值.size();++i)
                {

                    if(键值.size()>1 && i<键值.size() && i>0)//添加逗号
                    {   返回文本+=",";}
                    返回文本+=键值.at(i);
                }

            }

            if(!已找到 && in.atEnd())//没找到键名,并且已到结尾.
            {
                返回文本=键名+"=";
                for(int i=0;i<键值.size();++i)
                {
                    if(键值.size()>1 && i<键值.size() && i>0)//添加逗号
                    {    返回文本+=",";}
                    返回文本+=键值.at(i);
                }
            }
            新ini文件内容.append(返回文本);
        }
            file.resize(0);//清空原文件内容
        for(int i=0;i<新ini文件内容.size();++i)//将新内容写入到ini中.
        {
            in<<新ini文件内容.at(i)<<"\r\n";
        }
    }
    //错误处理未做.
    return 键名;
}

///把一行字符形的html语句拆分为多个字符列表元素.
QStringList 单行html元素拆分(QString html语句)
{
    QStringList html元素;
    int i左尖,i右尖;
    int 长度=html语句.length();
    QString 临时语句;
int i=200;
while(长度 && i){//i用来避免死循环。
    i--;

    i左尖= html语句.indexOf("<");
    if(i左尖==0)//第一个字符是"<"
    {

        i右尖= html语句.indexOf(">");
        if(i左尖<i右尖)
        {
            临时语句=html语句.mid(0,i右尖+1);//要把">"包括进去
            html元素.append(临时语句);
            html语句=html语句.mid(i右尖+1,长度-i右尖);
            长度=html语句.length();
        }
    }
    else if(i左尖>0)//第一个字符不是"<"
    {
        临时语句=html语句.mid(0,i左尖);//不要把"<"包括进去
        html元素.append(临时语句);
        html语句=html语句.mid(i左尖,长度-i左尖);
        长度=html语句.length();
    }
    else if(i左尖== -1)//不含有html标签
    {
        html元素.append(html语句);
        break;
    }
   // qDebug() << "html语句循环"<<html语句;

}
    //qDebug() << "html元素"<<html元素;

   return html元素;

}



QStringList 文本文件转字符列表(QString html文件)
{
    QStringList 返回字符列表;

    QFile file(html文件);
    if (file.open (QIODevice::ReadOnly))
    {
        QTextStream in(&file);
        in.seek(0); // 将文件指针移动到文件开头,计数是以字符计数，不是行数。

        while(!in.atEnd()) {
            返回字符列表.append(in.readLine());// 读取一行文本, 添加一行文本

        }
    }
    return 返回字符列表;
}

bool 文件复制到另一位置(QString 源文件, QString 目标路径)
{
  //  QString sourceFilePath = "D:/AA/sourceFile.txt";

    // 目标文件路径
 //   QString destinationFilePath = "C:/BB/destinationFile.txt";

    // 创建QFile对象并打开源文件
    QFile sourceFile(源文件);
    if (!sourceFile.open(QIODevice::ReadOnly)) {
        qDebug() << "无法打开源文件：" << 源文件;
        return false;
    }

    //如果目标的目录不存在, 创建目录.
    int index= 目标路径.lastIndexOf("/");
    QString dirName = 目标路径.mid(0,index);
    if (!QDir().exists(dirName)) {
    QDir().mkpath(dirName);
    }

    // 创建QFile对象并打开目标文件
    QFile destinationFile(目标路径);
    if (!destinationFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        qDebug() << "无法打开目标文件：" << 目标路径;
        sourceFile.close();
        return false;
    }

    // 复制文件内容
    while (!sourceFile.atEnd()) {
        QByteArray data = sourceFile.read(1024); // 以1KB为单位进行读取和写入，可以根据需要调整大小
        if (data.isEmpty()) {
            break;
        }
        destinationFile.write(data);
    }

    // 关闭文件
    sourceFile.close();
    destinationFile.close();

    qDebug() << "文件复制成功！";
    return true;

}

//生成建表需要的ini文件
//返回值不重要
QString 规整化笔记模板(QString INI文件)
{
    QStringList ini写入;

    ini写入.append("ID,标题,正文");//写入数据库的列名
    ini写入指定键值(INI文件,"<~>",ini写入);

    ini写入[0]="自动递增|不显示,,";//ID递增方式, ID不显示
    ini写入指定键值(INI文件,"<`>",ini写入);

    ini写入[0]="笔记";//表的类型是笔记
    ini写入指定键值(INI文件,"<^>",ini写入);

    ini写入[0]="标题,正文";//在窗口索引框显示的元素
    ini写入指定键值(INI文件,"<->",ini写入);

    QString 单行文本;

    return 单行文本;
}


//用于在索引框中显示时,去除尖括号
QString 去除尖括号并限制长度(QString 带尖括号语句)
{
    int index左尖;
    int index右尖;
    QString 返回文本;

    while(带尖括号语句.length())
    {
        index左尖=带尖括号语句.indexOf("<");
        index右尖=带尖括号语句.indexOf(">");
        if(index左尖== 0 && index右尖>0)
        {
            带尖括号语句=带尖括号语句.mid(index右尖+1,带尖括号语句.length()-index右尖-1);
        }
        if(index左尖> 0 && index右尖>index左尖)
        {
            返回文本+=带尖括号语句.mid(0,index左尖);
            带尖括号语句=带尖括号语句.mid(index左尖,带尖括号语句.length()-index左尖);
        }
      //  qDebug() <<"尖括号 "<< index左尖<<index右尖<<返回文本<<带尖括号语句;
        if(index左尖== -1 || index右尖 ==-1)//没有带尖括号的,直接把原语句返回.
        {
            返回文本=带尖括号语句;
            break;
        }

    }
    if(返回文本.length()>50)//限制长度为50;
    {
         返回文本=返回文本.mid(0,50);
    }

    return 返回文本;
}
